import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { In, Repository } from 'typeorm';
import { CreateMajorDto, UpdateMajorDto, QueryMajorDto } from '@dto/major.dto';
import { MajorEntity } from '@entity/major.entity';
import { resBuild } from '../utils/resBuild';
import { getOperator, isEmpty } from '../utils';
import { SysDept } from '@entity/framework/system/SysDept';
import { GradeEntity } from '@entity/grade.entity';
@Provide()
export class MajorDao {
  @Inject()
  ctx: Context;
  @InjectEntityModel(MajorEntity)
  majorEntityRep: Repository<MajorEntity>;

  @InjectEntityModel(GradeEntity)
  gradeEntityRep: Repository<GradeEntity>;

  @InjectEntityModel(SysDept)
  sysDeptEntityRep: Repository<SysDept>;



  async create(createMajorDto: CreateMajorDto) {
    const { gradeId } = createMajorDto;
    if (!gradeId && gradeId !== 0) {
      return resBuild.error('请先选择年级后再创建专业');
    }
    const grade = await this.gradeEntityRep.findOne({
      where: {
        gradeId: gradeId as number,
      },
    });

    if (!grade) {
      return resBuild.error(`年级ID ${gradeId} 不存在`);
    }
    if (grade.status !== '0') {
      return resBuild.error(`年级 ${grade.gradeName} 已停用`);
    }
    if (grade.delFlag === '2') {
      return resBuild.error(`年级 ${grade.gradeName} 已删除`);
    }
   createMajorDto.groupFlag = '0';
   createMajorDto.status = '0';
    const entity = this.majorEntityRep.create(createMajorDto);
    entity.setCreateBy(getOperator(this.ctx));
    entity.setUpdateBy(getOperator(this.ctx));
    try {
      await this.majorEntityRep.save(entity);
      return resBuild.success();
    } catch (error) {
      if (error.code === '23505' && error.constraint === 'major_pkey') {
        return resBuild.error('专业创建失败：主键冲突，请联系管理员修复数据库序列');
      }
      throw error;
    }
  }

  async list(query: QueryMajorDto) {
    const entity = this.majorEntityRep
      .createQueryBuilder('entity')
      .leftJoin('entity.grade', 'grade')
      .leftJoin(SysDept, 'dept', 'dept.deptId = grade.deptId')
      .where('entity.delFlag = :delFlag', { delFlag: '0' });

    if (!isEmpty(query.gradeId)) {
      entity.andWhere('entity.gradeId = :gradeId', { gradeId: query.gradeId });
    }
    if (!isEmpty((query as any).deptId)) {
      entity.andWhere('grade.deptId = :deptId', { deptId: (query as any).deptId });
    }
    if (!isEmpty(query.majorName)) {
      entity.andWhere('entity.majorName ILIKE :majorName', {
        majorName: `%${query.majorName}%`,
      });
    }
    if (!isEmpty(query.gradeMajorName)) {
      entity.andWhere('entity.gradeMajorName ILIKE :gradeMajorName', {
        gradeMajorName: `%${query.gradeMajorName}%`,
      });
    }
    if (!isEmpty(query.groupFlag)) {
      entity.andWhere('entity.groupFlag = :groupFlag', {
        groupFlag: query.groupFlag,
      });
    }
    if (!isEmpty(query.status)) {
      entity.andWhere('entity.status = :status', { status: query.status });
    }

    // 扁平化输出字段，并用引号包裹别名以确保驼峰命名不被数据库驱动折叠
    entity.select([
      'entity.majorId AS "majorId"',
      'entity.gradeId AS "gradeId"',
      'entity.majorName AS "majorName"',
      'entity.gradeMajorName AS "gradeMajorName"',
      'entity.groupFlag AS "groupFlag"',
      'entity.remark AS "remark"',
      'entity.status AS "status"',
      'grade.gradeName AS "gradeName"',
      'grade.deptId AS "deptId"',
      'dept.deptName AS "deptName"',
    ]);

    if (query.pageNum && query.pageSize) {
      entity.skip(query.pageSize * (query.pageNum - 1)).take(query.pageSize);
    }
    entity.addOrderBy('entity.createTime', 'DESC');

    const [list, total] = await Promise.all([entity.getRawMany(), entity.getCount()]);
    return resBuild.list(list, total);
  }

  async detail(majorId: number) {
    const qb = this.majorEntityRep
      .createQueryBuilder('entity')
      .leftJoin('entity.grade', 'grade')
      .leftJoin(SysDept, 'dept', 'dept.deptId = grade.deptId')
      .where('entity.majorId = :majorId', { majorId })
      .andWhere('entity.delFlag = :delFlag', { delFlag: '0' })
      .select([
        'entity.majorId AS "majorId"',
        'entity.gradeId AS "gradeId"',
        'entity.majorName AS "majorName"',
        'entity.gradeMajorName AS "gradeMajorName"',
        'entity.groupFlag AS "groupFlag"',
        'entity.remark AS "remark"',
        'entity.status AS "status"',
        'entity.createTime AS "createTime"',
        'entity.updateTime AS "updateTime"',
        'entity.createBy AS "createBy"',
        'entity.updateBy AS "updateBy"',
        'grade.gradeName AS "gradeName"',
        'grade.deptId AS "deptId"',
        'dept.deptName AS "deptName"'
      ]);

    const detailInfo = await qb.getRawOne();
    return resBuild.data(detailInfo);
  }

  async update(updateMajorDto: UpdateMajorDto) {
    const entity = this.majorEntityRep.create(updateMajorDto);
    entity.setUpdateBy(getOperator(this.ctx));
    await this.majorEntityRep.save(entity);
    return resBuild.success();
  }

  async remove(majorIds: Array<number>) {
    await this.majorEntityRep.update(
      { majorId: In(majorIds) },
      {
        delFlag: '1',
        updateBy: getOperator(this.ctx),
        updateTime: new Date(),
      }
    );
    return resBuild.success();
  }

  /**
   * 根据年级ID获取专业列表（不分页）
   */
  async listByGrade(gradeId: number) {
    const groupFlag = '0';
    const majors = await this.majorEntityRep
      .createQueryBuilder('entity')
      .leftJoinAndSelect('entity.grade', 'grade')
      .where('entity.gradeId = :gradeId', { gradeId })
      .andWhere('entity.delFlag = :delFlag', { delFlag: '0' })
      .andWhere('entity.groupFlag= :groupFlag', {groupFlag})
      .orderBy('entity.createTime', 'DESC')
      .getMany();

    return resBuild.data(majors);
  }

  //获取院系下的所有年级
  async getGradeList(){
    const qb = this.gradeEntityRep
      .createQueryBuilder('grade')
      .leftJoin(SysDept, 'dept', 'dept.deptId = grade.deptId')
      .where('grade.delFlag = :delFlag', { delFlag: '0' })
      .andWhere('grade.status = :status', { status: '0' })
      .andWhere('dept.delFlag = :deptDelFlag', { deptDelFlag: '0' })
      .select([
        'grade.gradeId AS "gradeId"',
        'grade.deptId AS "deptId"',
        'grade.gradeName AS "gradeName"',
        'dept.deptName AS "deptName"',
      ])
      .orderBy('dept.orderNum', 'ASC')
      .addOrderBy('grade.createTime', 'DESC');

    const list = await qb.getRawMany();
    return resBuild.data(list);
  }

}
